﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Microsoft.AspNetCore.Mvc;
using shenghua.Authorization;
using shenghua.Basics.ShippingTemplates;
using shenghua.Common.Dto;
using shenghua.Member.ShippingAddresses;
using shenghua.Order.Orders.Dto;
using shenghua.Order.Refunds;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace shenghua.Order.Orders
{
    [AbpAuthorize(PermissionNames.OrderManagement)]
    public class AdminOrderManagerAppService: shenghuaAppServiceBase, IAdminOrderManagerAppService
    {
        private readonly OrderManager _orderManager;
        private readonly IRepository<Order> _orderRepository;
        private readonly ShippingTemplateManager _shippingTemplateManager;
        private readonly RefundManager _refundManager;

        public AdminOrderManagerAppService(
            OrderManager orderManager,
            IRepository<Order> orderRepository,
            ShippingTemplateManager shippingTemplateManager,
            RefundManager refundManager
            )
        {
            _orderManager = orderManager;
            _orderRepository = orderRepository;
            _shippingTemplateManager = shippingTemplateManager;
            _refundManager = refundManager;
        }

        /// <summary>
        /// 更新订单，是在订单基础上做一定修改，不能涉及状态的改变
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<OrderDto> Update(UpdateOrderDto input)
        {
            Order order = await _orderManager.Get(null, input.OrderNumber);

            if (order.PaymentInfo.PaymentStatus == OrderPaymentStatus.PendingPay && order.ShipInfo.ShipStatus == OrderShipStatus.PendingShip)
            {
                MemberShippingAddress deliveryAddress = new MemberShippingAddress
                {
                    PersonName = input.PersonName,
                    PhoneNumber = input.PhoneNumber,
                    Province = input.Province,
                    City = input.City,
                    County = input.County,
                    DetailedAddress = input.DetailedAddress
                };
                ShippingTemplate shippingTemplate = await _shippingTemplateManager.GetValid(input.ShippingTemplateId);
                await _orderManager.UpdateOrderDeliveryAddressAndShippingTemplate(order, deliveryAddress, shippingTemplate);
            }

            if (order.PaymentInfo.PaymentStatus == OrderPaymentStatus.PendingPay)
            {
                await _orderManager.AdjustOrderAmount(order, input.AdjustmentAmount);
            }

            //await _orderManager.UpdatePaymentInfo(order, input.PaymentType, input.PaymentMethod, input.IsPaid);
            await _orderManager.SetAdminRemark(order, input.AdminRemark);

            return null;
        }

        public async Task ConfirmPayment(ConfirmPaymentDto input)
        {
            Order order = await _orderManager.Get(null, input.OrderNumber);
            await _orderManager.ConfirmPayment(order, new OrderPaymentInfo
            {
                PaymentType = input.PaymentType,
                PaymentMethod = input.PaymentMethod,
                TradeNumber = input.TradeNumber,
                Remark = input.Remark
            });
        }

        /// <summary>
        /// 发货
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SetShipped(OrderShippedDto input)
        {
            if (input.wuliuType == OrderShipInfo.OrderShipWuliuType.Default)
            {
                await _orderManager.SetShipped(input.OrderNumber, input.Number, input.ExpressType, input.ExpressName);
            }
            else
            {
                await _orderManager.SetShipped(input.OrderNumber, input.CustomWuliuInfo);
            }
        }

        public async Task<SearchResultDto<OrderDto>> Search(SearchOrderDto input)
        {
            var query = _orderRepository.GetAll();

            if(!string.IsNullOrWhiteSpace(input.Search))
            {
                switch (input.SearchTarget)
                {
                    case "orderNumber": query = query.Where(r => r.OrderNumber == input.Search); break;
                    case "userName": query = query.Where(r => r.MemberInfo.UserName == input.Search); break;
                    case "phoneNumber": query = query.Where(r => r.ShipInfo.PhoneNumber == input.Search); break;
                    case "subject": query = query.Where(r => r.Info.Subject.Contains(input.Search)); break;
                }
            }

            if(input.Begin != null)
            {
                query = query.Where(r => r.Info.CreationTime >= input.Begin);
            }

            if (input.End != null)
            {
                query = query.Where(r => r.Info.CreationTime <= input.End);
            }

            if (!string.IsNullOrWhiteSpace(input.Status))
            {
                switch (input.Status)
                {
                    case "all": break;
                    case "pendingPay": query = query.Where(r => r.Info.Status == Median.OrderStatus.Created && r.PaymentInfo.PaymentStatus == OrderPaymentStatus.PendingPay); break;
                    case "pendingShip": query = query.Where(r => r.Info.Status == Median.OrderStatus.Created && r.ShipInfo.ShipStatus == OrderShipStatus.PendingShip); break;
                    case "shipped": query = query.Where(r => r.Info.Status == Median.OrderStatus.Created && r.ShipInfo.ShipStatus == OrderShipStatus.Shipped); break;
                    case "pendingFinish": query = query.Where(r => r.Info.Status == Median.OrderStatus.Created && r.ShipInfo.ShipStatus == OrderShipStatus.Received && r.PaymentInfo.PaymentStatus == OrderPaymentStatus.Paid); break;
                    case "finished": query = query.Where(r => r.Info.Status == Median.OrderStatus.Succeeded); break;
                    case "closed": query = query.Where(r => r.Info.Status == Median.OrderStatus.Closed); break;
                }
            }

            var totalCount = query.Count();
            var items = query.OrderByDescending(r => r.Info.CreationTime).Skip(input.SkipCount).Take(input.MaxResultCount).ToList();

            List<OrderDto> orderDtos = new List<OrderDto>();
            foreach (var item in items)
            {
                var details = await _orderManager.GetDetails(item.Id);
                orderDtos.Add(new OrderDto(item, details));
            }

            return new SearchResultDto<OrderDto>
            {
                TotalCount = totalCount,
                Items = orderDtos
            };
        }

        public async Task<OrderDto> Get(OrderNumberDto input)
        {
            var item = await _orderManager.Get(null, input.OrderNumber);
            var details = await _orderManager.GetDetails(item.Id);
            return new OrderDto(item, details);
        }

        /// <summary>
        /// 删除和批量删除
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task Delete(OrderNumberDto input)
        {
            foreach(var orderNumber in input.OrderNumbers)
            {
                await _orderManager.DeleteOrder(null, orderNumber);
            }
        }

        /// <summary>
        /// 完成订单和批量完成订单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SetFinish(OrderNumberDto input)
        {
            foreach (var orderNumber in input.OrderNumbers)
            {
                await _orderManager.FinishedOrder(null, orderNumber);
            }
        }

        /// <summary>
        /// 批量发货
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SetShippedBatch(OrderShippedBatchDto input)
        {
            foreach (var item in input.Items)
            {
                await SetShipped(item);
            }
        }

        /// <summary>
        /// 获取物流信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<OrderShipWuliuDto> GetOrderWuliu(OrderNumberDto input)
        {
            try
            {
                var orderShipWuliu = await _orderManager.GetOrderWuliu(null, input.OrderNumber);
                return ObjectMapper.Map<OrderShipWuliuDto>(orderShipWuliu);
            }
            catch (Exception e)
            {
                var result = new OrderShipWuliuDto();
                result.Errors.Add(e.Message);
                return result;
            }
        }

        /// <summary>
        /// 得到订单的所有日志
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<OrderLogDto>> GetAllOrderLogs(OrderNumberDto input)
        {
            var items = await _orderManager.GetAllOrderLogs(null, input.OrderNumber);
            return ObjectMapper.Map<List<OrderLogDto>>(items);
        }

        #region 退款处理
        public async Task<RefundDto> AddRefund(AddRefundDto input)
        {
            Refund refund = new Refund
            {
                RefundAmount = input.RefundAmount,
                Description = input.Description,
                Status = input.Status,
                Remark = input.Remark
            };
            Order order = await _orderManager.Get(null, input.OrderNumber);
            await _refundManager.Add(order, refund);
            return ObjectMapper.Map<RefundDto>(refund);
        }

        public async Task<RefundDto> UpdateRefund(UpdateRefundDto input)
        {
            var item = await _refundManager.Get(input.Id);
            item.RefundAmount = input.RefundAmount;
            item.Status = input.Status;
            item.Description = input.Description;
            item.Remark = input.Remark;
            await _refundManager.Update(item);
            return ObjectMapper.Map<RefundDto>(item);
        }

        [HttpPost]
        public async Task DeleteRefund(EntityDto input)
        {
            await _refundManager.Delete(input.Id);
        }

        public async Task<List<RefundDto>> GetOrderRefunds(OrderNumberDto input)
        {
            var items = await _refundManager.GetAllOfOrder(null, input.OrderNumber);
            return ObjectMapper.Map<List<RefundDto>>(items);
        }
        #endregion
    }
}
